#include <iostream>
#include <vector>
#include <sstream>
#include <stdlib.h> //atoi
#include <time.h>
#include <bitset>
#include "stringhelper.h"
#include "csvpp.h"

using namespace std;
using namespace csvpp;

template <class T>
inline string ToString(const T& t)
{
	stringstream ss;
	ss << t;
	return ss.str();
}

string str_pad(string s, unsigned int num, char pad)
{
	string tmppad;
	if (s.length() <= num)
		for(unsigned int i = (num - s.length()); i > 0; i--)
			tmppad = tmppad + pad;
	return tmppad + s;
}

string tobin(int dec)
{
        if (dec > 0)
                return tobin(dec/2) + ToString(dec%2);
        return "";
}

int main()
{
	srand ( (unsigned int)time(NULL) );
	string csvrows;
	rows csvfile;
	ROW r;
	vector<string> ip_addr_arr;
	csvrows = "id,ip_addr,rndnum,rndstr\n";
	string randchars = "ABCDEFGHIJKLMNOPZRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
	string ip_addr;
	string randnum;
	string randstr;
	int oct1;
	int oct2;
	int oct3;
	int oct4;
	int oct1high;
	int oct2high;
	int oct3high;
	int oct4high;
	string combinedoct;
	unsigned int csvsize;
	unsigned long int curraddr = 0;
	unsigned long int highestaddr = 0;
	for(int i = 0; i < 999999; i++)
	{
		randstr = "";
		ip_addr = ToString(rand() % (255 - 1 + 1) + 1) + "." + ToString(rand() % (255 - 1 + 1) + 1) + "." + ToString(rand() % (255 - 1 + 1) + 1) + "." + ToString(rand() % (255 - 1 + 1) + 1);
		randnum = ToString(rand() % 9999);
		for(int x = 0; x < 10; x++)
			randstr += randchars.at(rand() % (61));
		csvrows += ToString(i)+","+ip_addr+","+randnum+","+randstr+"\n";
	}
	CSV reader;
	reader.set(csvrows);
	csvrows = "";
	reader.write("/tmp/csv.tmp");
	reader.open("/tmp/csv.tmp");
	csvfile = reader.read();
	csvsize = csvfile.size();
	for(unsigned int i = 0; i < csvsize; i++)
	{
		r = csvfile.at(i);
		ip_addr_arr = split(r["ip_addr"], ".");
		
		oct1 = atoi(ip_addr_arr.at(0).c_str());
		oct2 = atoi(ip_addr_arr.at(1).c_str());
		oct3 = atoi(ip_addr_arr.at(2).c_str());
		oct4 = atoi(ip_addr_arr.at(3).c_str());


		combinedoct = str_pad(tobin(oct1), 8, '0');
		combinedoct += str_pad(tobin(oct2), 8, '0');
		combinedoct += str_pad(tobin(oct3), 8, '0');
		combinedoct += str_pad(tobin(oct4), 8, '0');
		
		curraddr = bitset<32>(combinedoct).to_ulong();
		if (curraddr > highestaddr)
			highestaddr = curraddr;
	}

	cout << "Highest IP Address generated (Decimal): " << highestaddr << endl;
	oct4high = highestaddr & 0xFF;
	oct3high = ( highestaddr >> 8 ) & 0xFF;
	oct2high = ( highestaddr >> 16 ) & 0xFF;
	oct1high = ( highestaddr >> 24 ) & 0xFF;
	cout << "Highest IP Address generated (Dotted): " << oct1high << "." << oct2high << "." << oct3high << "." << oct4high << endl;
	return 0;
}